﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;

namespace RehabilitationRobot
{
    public class MotionController
    {
        /* 声明Parker运动控制器库文件接口 */
        ComACRServerLib.Channel channel = new ComACRServerLib.Channel();

        #region 减速比设定

        /*机器人关节脉冲速度，其值根据电机的编码器精度决定，即电机每转一圈需要控制器下发的脉冲数*/
        public const double _PPU = 16384.0 / 360.0; 

        /*左髋减速比*/
        public const double TransRatio_HL = 250;

        /*右髋减速比*/
        public const double TransRatio_HR = 250;

        /*左膝减速比*/
        public const double TransRatio_KL = 50;

        /*右膝减速比*/
        public const double TransRatio_KR = 50;

        #endregion

        #region 状态管理（Parker）      
        public struct Controller
        {
            public bool Controller_Connect;
            public bool Controller_AllMotion_DriveOn;
            public bool Controller_Drives_Fault;
            public bool Controller_ElePutter_Running;
            public bool Controller_LimitSwitch;
            public bool Controller_SoftwareLimit;
            public bool Controller_AxisOrigin;
            public bool Controller_MoveBuffer;

        }
        public struct UpperComputer
        {
            public bool JogMode_Running;
            public bool RehabitMode_Running;
            public bool AngSensor_Connect;
            public bool TorqueSensor_Connect;
            
        }
        public struct AxisGroup
        {
            public bool Group_Acc;
            public bool Group_Dec;
            public bool Group_Stp;
            public bool Group_Jek;
            public bool Group_InMotion;
            public bool Group_MVBF;
            public bool Group_Feedholding;
            public bool Group_InFeedhold;
        }

        public Controller Controller_State;
        public UpperComputer UpperComputer_State;
        public AxisGroup AxisGroup_State;
        #endregion

        #region 变量定义

        /* 实时角度读取存储数组 */
        internal double[] m_dRealTimeAngle =new double[4];

        /* 运动缓冲区变量 */
        /*-------------------------------------------------------*/
        internal int m_iMoveBuffers
        { 
            get ;
            set ; 
        }
        internal  int m_iMoveCounters;
        internal  int m_iMoveBufferLeftStream;
        /*-------------------------------------------------------*/





        /* 跟踪误差 */
        internal double[] m_dRealFollowingError = new double[4];




        /* 软件限位相关 */
        /*-------------------------------------------------------*/
        /* 软件限位P参数 */
        internal int m_iProgram1Flags_P4600;
        internal int m_iProgram1Flags_P4601;
        internal int m_iProgram1Flags_P4602;
        internal int m_iProgram1Flags_P4603;

        /* 软件限位Bit参数 */
        internal bool m_bIsBit16136;
        internal bool m_bIsBit16137;
        internal bool m_bIsBit16168;
        internal bool m_bIsBit16169;
        internal bool m_bIsBit16200;
        internal bool m_bIsBit16201;
        internal bool m_bIsBit16232;
        internal bool m_bIsBit16233;
        /*-------------------------------------------------------*/




        /* 使能状态读取 */
        /*-------------------------------------------------------*/
        /* 各轴Axis Flags的P参数 */
        internal int m_lAxis0Flags_P4360;
        internal int m_lAxis1Flags_P4361;
        internal int m_lAxis2Flags_P4362;
        internal int m_lAxis3Flags_P4363;

        /* 各轴使能状态Bit参数 */
        internal bool m_bIsEnableHL;
        internal bool m_bIsEnableHR;
        internal bool m_bIsEnableKL;
        internal bool m_bIsEnableKR;
        /*-------------------------------------------------------*/




        /* Program2相关 */
        internal int m_iProgram1Flags_P4130;
        internal bool m_bIsBit1088;




        /* 限位开关相关 */
        /*-------------------------------------------------------*/
        /* IO相关的P参数 */
        internal int m_iProgram1Flags_P4096;

        /* 外接IO，连接限位开关 */
        internal bool m_bIsBit24;
        internal bool m_bIsBit25;
        internal bool m_bIsBit26;
        internal bool m_bIsBit27;
        internal bool m_bIsBit28;
        internal bool m_bIsBit29;
        internal bool m_bIsBit30;
        internal bool m_bIsBit31;
        /*-------------------------------------------------------*/




        /* 自定义Bit参数255 */
        internal int m_iProgram1Flags_P4103;
        internal bool m_bIsBit255;




        /* 轴组状态（Paker提供） */
        internal int m_iProgram1Flags_P4112;

        /* 驱动器错误（Drive fault input）*/
        internal int m_iProgram1Flags_P4098;
        internal bool m_bIsBit64;
        internal bool m_bIsBit65;
        internal bool m_bIsBit66;
        internal bool m_bIsBit67;

        #endregion

        #region 运动控制器方法相关
        internal void ConnectController()
        {
            #region Parker运动控制器相关

            /* Parker默认IP地址 */
            channel.bstrIP = "192.168.10.40";

            /* Paker第三种连接方式为EtherNet */
            channel.Connect(3, 0);

            if (channel.isOffline == false)
            {
                ConnectInitialize();                
            }
            #endregion 
        }

        /* 检测控制器连接状态 */
        internal void CheckConnectControllerStatus()
        {
            Controller_State.Controller_Connect = channel.TestConnect();
        }

        internal void ConnectInitialize()
        {
            try
            {
                /* 将master 0的运动计数置为0 */
                channel.Write("P8208=0\r");

                /* 开辟一个PROG文档，为下面Write();所必须 */
                channel.Write("PROG0" + "\r");

                /* 设置各关节的加速度，写入PROG 0中 */
                channel.Write("JOG ACC X 600\r"); 
                channel.Write("JOG ACC Y 600\r");
                channel.Write("JOG ACC Z 600\r");
                channel.Write("JOG ACC A 600\r");

                /* 设置各关节的减速度，写入PROG 0中 */
                channel.Write("JOG DEC X 500\r");	 
                channel.Write("JOG DEC Y 500\r");
                channel.Write("JOG DEC Z 500\r");
                channel.Write("JOG DEC A 500\r");

                /* 反向间隙补偿测试20171121，回程运动时，补偿-5个脉冲 */
                channel.Write("BKL X-0.0025\r");	
                channel.Write("BKL Y-0.0025\r");     
                channel.Write("BKL Z-0.0025\r");     
                channel.Write("BKL A-0.0025\r");

                /* 开辟1000的内存 */
                channel.Write("CLEAR" + "\r");      
                channel.Write("DIM MBUF(400)" + "\r");
                channel.Write("MBUF ON" + "\r");

                /* 设置matser的加速度 */
                channel.Write("ACC 800\r");

                /* 设置matser的减速度 */
                channel.Write("DEC 800\r");

                /* 设置Master的停止速度为800 */
                channel.Write("STP 800\r");

                /* 最终速度  FVEL值，设置太大，减速到FVEL值后，也是瞬间减速到0，冲击很大 */
                channel.Write("FVEL 0\r");

                /* 初始速度 由于加速度是系统默认的，此值太大导致加速度过大，冲击很大 */
                channel.Write("IVEL 0\r");

                /* 设置成连续运动模式 */
                channel.nMoveMode = 0;

                /* 设置成绝对式 */
                channel.bMoveAbsolute = true;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        

        internal void DisconnectController()
        {
            /* 关闭MBUF */
            channel.SetFlag(5898, false, true);

            /* 断开连接 */
            channel.Disconnect(); 
          
        }

        /* 伺服使能方法 */
        internal void ServoOn() 
        {
            #region Parker使能方法

            /* 设置轴组0的KILL ALL MOVES参考《ComACRsrvr UG》的P47和P49 */
            channel.SetFlag(522, false, false);

            /* 设置轴组0的STOP ALL MOVES*/
            channel.SetFlag(523, false, false);//

            /* 设置4个轴的Kill all the move request */
            channel.SetFlag(8467, false, true); 
            channel.SetFlag(8499, false, true);      
            channel.SetFlag(8531, false, true);
            channel.SetFlag(8563, false, true);

            /* 设置4个轴的Drive Enable Output为使能 */
            channel.SetFlag(8465, true, true);
            channel.SetFlag(8497, true, true);
            channel.SetFlag(8529, true, true);
            channel.SetFlag(8561, true, true);
                        
            #endregion                  
        }


        /* 伺服禁能函数 */
        internal void ServoOff() 
        {
            /* 设置4个轴的Drive Enable Output为禁能 */
            channel.SetFlag(8465, false, true);  
            channel.SetFlag(8497, false, true); 
            channel.SetFlag(8529, false, true);  
            channel.SetFlag(8561, false, true); 
            
        }

        /* 允许机器运行 */
        internal void RobotMoveAllow()
        {
            /* 轴组0的Kill All Move标志位置零 */
            channel.SetFlag(522, false, true);

            /* 设置4个轴的Kill All Motion Request标志位置零 */
            channel.SetFlag(8467, false, true);
            channel.SetFlag(8499, false, true);
            channel.SetFlag(8531, false, true);
            channel.SetFlag(8563, false, true);
        }

        /* 禁止机器运行 */
        internal void RobotMoveForbid()
        {
            /* 轴组0的Kill All Move标志位置1 */
            channel.SetFlag(522, true, true);

            /* 设置4个轴的Kill All Motion Request标志位置1 */
            channel.SetFlag(8467, true, true);
            channel.SetFlag(8499, true, true);
            channel.SetFlag(8531, true, true);
            channel.SetFlag(8563, true, true);
        }

        /* Dh清零 */
        internal void DhClear()
        {
            /* 4个轴的编码器信息全清零 */
            channel.SendRES(15);
        }

        /* Paker运动控制器核心方法Move */
        internal void RobotMoveDownload(double[] angle,double velocity)
        {
            if(velocity == 0.0)
            {
                velocity = 0.0001f;
            }

            /* 接收的速度值为合角速度，parker控制器内部会自己分解成六个关节的角速度，分解机理不清楚 */
            channel.fMoveVEL = (float)velocity;

            channel.fMoveACC = (float)velocity * 10000;
            object[] DownloadAngle = new object[4];

            for (int i = 0; i < 4; i++)
            {
                DownloadAngle[i] = angle[i];
            }
            /* 四关节联动，Parker运动控制器核心函数MOVE */
            channel.Move(15, DownloadAngle);
        }

        /* 点动模块 */
        internal void AxisJog(int AxisNum,int Direction,double Vel)
        {
            /* 设置点动步进量为5度 */
            double UnitMoveAngle = 5.0;
            double[] GetAngle = new double[4];

            if ((Direction == 1) || (Direction == -1))
            {
                /* 先获取当前实际角度值 */
                for (int i = 0; i < 4; i++)
                {
                    GetAngle[i] = m_dRealTimeAngle[i];
                }

                #region 按轴下发
                switch (AxisNum)
                {
                    case 1:
                        {
                            GetAngle[0] = GetAngle[0] + (double)Direction*UnitMoveAngle;
                            if(m_iMoveBuffers<50)
                            {
                                RobotMoveDownload(GetAngle, Vel);
                            }
                        }
                        break;
                    case 2:
                        {
                            GetAngle[1] = GetAngle[1] + (double)Direction * UnitMoveAngle;
                            if (m_iMoveBuffers < 50)
                            {
                                RobotMoveDownload(GetAngle, Vel);
                            }
                        }
                        break;
                    case 3:
                        {
                            GetAngle[2] = GetAngle[2] + (double)Direction * UnitMoveAngle;
                            if (m_iMoveBuffers < 50)
                            {
                                RobotMoveDownload(GetAngle, Vel);
                            }
                        }
                        break;
                    case 4:
                        {
                            GetAngle[3] = GetAngle[3] + (double)Direction * UnitMoveAngle;
                            if (m_iMoveBuffers < 50)
                            {
                                RobotMoveDownload(GetAngle, Vel);
                            }
                        }
                        break;


                }
                #endregion

            }
            else
            {
                MessageBox.Show("转动方向错误");
            }
        }

        #region 全部归零
        internal void GotoZero()
        {
            RobotMoveAllow();
            double[] OrgAng = new double[4] { 0, 0, 0, 0 };
            RobotMoveDownload(OrgAng, 4);
            AlltoZeroDelay();
        }

        /// <summary>
        /// 未回零点则延时
        /// </summary>
        internal void AlltoZeroDelay()
        {
            Delay(5);
            if (Controller_State.Controller_AxisOrigin) return;
            else
            {
                AlltoZeroDelay();
            }
        }

        /// <summary>
        /// 延时程序
        /// </summary>
        /// <param name="delayTime">延时时间</param>
        /// <returns>运行成功</returns>
        public static bool Delay(int delayTime)
        {
            DateTime now = DateTime.Now;
            int s;
            do
            {
                TimeSpan spand = DateTime.Now - now;
                s = spand.Milliseconds;
                Application.DoEvents();
            }
            while (s < delayTime);
            return true;
        }
        #endregion
        
        #region Paker中P参数和Bit参数获取
        /* 角度读取及零点定义 */
        internal void AngleRead()
        {
            string AngleReadParameter = "P12290,P12546,P12802,P13058";
            Array GetPParms = channel.GetACRCustom(AngleReadParameter);

            #region 实时角度读取

            /* 提取GetPParms.GetValue(0)的object类型数据，强制转换成double型，经过脉冲比、减速比换算成实际运动关节角度值
             * 伺服电机编码器线数为16位，4分频后为14位，即2的14次方为16384，即PPU = 16384/360 */
            m_dRealTimeAngle[0] = (Convert.ToDouble(GetPParms.GetValue(0)) / _PPU)
                / TransRatio_HL;

            m_dRealTimeAngle[1] = (Convert.ToDouble(GetPParms.GetValue(1)) / _PPU)
                / TransRatio_HR;

            m_dRealTimeAngle[2] = (Convert.ToDouble(GetPParms.GetValue(2)) / _PPU)
                / TransRatio_KL;

            m_dRealTimeAngle[3] = (Convert.ToDouble(GetPParms.GetValue(3)) / _PPU)
                / TransRatio_KR;
            #endregion

            #region 机器人关节零点
            if ((Math.Abs(m_dRealTimeAngle[0]) < 0.3f) && (Math.Abs(m_dRealTimeAngle[1]) < 0.3f)
                && (Math.Abs(m_dRealTimeAngle[2]) < 0.3f) && (Math.Abs(m_dRealTimeAngle[3]) < 0.3f))
            {
                Controller_State.Controller_AxisOrigin = true;
                
            }
            else
            {
                Controller_State.Controller_AxisOrigin = false;
            }
            #endregion
        }

        /* 运动缓存区读取及状态设定 */
        internal void MoveBufferRead()
        {
            string MoveBufferStr = "P8212,P8208,P7072";
            Array GetPParms = channel.GetACRCustom(MoveBufferStr);
            #region 运动缓存区相关
            /* 提取GetPParms.GetValue(6)的值，将其转换为长整型，其值为运动缓冲区的指令个数 */
            m_iMoveBuffers = Convert.ToInt32(GetPParms.GetValue(0));
            /* 执行move指令的个数 */
            m_iMoveCounters = Convert.ToInt32(GetPParms.GetValue(1));
            /* 缓冲区剩余的运动指令个数 */
            m_iMoveBufferLeftStream = Convert.ToInt32(GetPParms.GetValue(2));
            #endregion

            if (m_iMoveBuffers < 50)
            {
                Controller_State.Controller_MoveBuffer = true;
            }
            else
            {
                Controller_State.Controller_MoveBuffer = false;
            }
        }

        /* 跟踪误差读取 */
        internal void FollowErrrRead()
        {
            string FollowingErrorStr = "P12291,P12547,P12803,P13059";
            Array GetPParms = channel.GetACRCustom(FollowingErrorStr);

            #region  跟踪误差
            m_dRealFollowingError[0] = Convert.ToDouble(GetPParms.GetValue(0));
            m_dRealFollowingError[1] = Convert.ToDouble(GetPParms.GetValue(1));
            m_dRealFollowingError[2] = Convert.ToDouble(GetPParms.GetValue(2));
            m_dRealFollowingError[3] = Convert.ToDouble(GetPParms.GetValue(3));
            #endregion
        }

        /* 软件限位状态读取 */
        internal void CheckSoftwareLimit()
        {
            string SoftwareLimitStr = "P4600,P4601,P4602,P4603";
            Array GetPParms = channel.GetACRCustom(SoftwareLimitStr);

            #region Parker软件限位
            /* P4600至P4603为轴标志位，第8位和第9位Bit位为软件限位标志位 */
            m_iProgram1Flags_P4600 = Convert.ToInt32(GetPParms.GetValue(0));
            m_iProgram1Flags_P4601 = Convert.ToInt32(GetPParms.GetValue(1));
            m_iProgram1Flags_P4602 = Convert.ToInt32(GetPParms.GetValue(2));
            m_iProgram1Flags_P4603 = Convert.ToInt32(GetPParms.GetValue(3));

            m_bIsBit16136 = channel.IsFlagSet(m_iProgram1Flags_P4600, 8);
            m_bIsBit16137 = channel.IsFlagSet(m_iProgram1Flags_P4600, 9);

            m_bIsBit16168 = channel.IsFlagSet(m_iProgram1Flags_P4601, 8);
            m_bIsBit16169 = channel.IsFlagSet(m_iProgram1Flags_P4601, 9);

            m_bIsBit16200 = channel.IsFlagSet(m_iProgram1Flags_P4602, 8);
            m_bIsBit16201 = channel.IsFlagSet(m_iProgram1Flags_P4602, 9);

            m_bIsBit16232 = channel.IsFlagSet(m_iProgram1Flags_P4603, 8);
            m_bIsBit16233 = channel.IsFlagSet(m_iProgram1Flags_P4603, 9);
            #endregion

            #region 软件限位状态获取

            if (m_bIsBit16136 || m_bIsBit16137 || m_bIsBit16168 || m_bIsBit16169
                || m_bIsBit16200 || m_bIsBit16201 || m_bIsBit16232 || m_bIsBit16233)
            {
                Controller_State.Controller_SoftwareLimit = true;
            }
            else
            {
                Controller_State.Controller_SoftwareLimit = false;
            }
            #endregion
        }

        /* 使能状态读取 */
        internal void CheckServoOn()
        {
            string m_stateGet = "P4360,P4361,P4362,P4363";
            Array GetPParms = channel.GetACRCustom(m_stateGet);
            m_lAxis0Flags_P4360 = Convert.ToInt32(GetPParms.GetValue(0));    //读取P4360的P参数
            m_lAxis1Flags_P4361 = Convert.ToInt32(GetPParms.GetValue(1));   //读取P4361的P参数
            m_lAxis2Flags_P4362 = Convert.ToInt32(GetPParms.GetValue(2));   //读取P4362的P参数
            m_lAxis3Flags_P4363 = Convert.ToInt32(GetPParms.GetValue(3));   //读取P4363的P参数

            m_bIsEnableHL = channel.IsFlagSet(m_lAxis0Flags_P4360, 28); //读取P参数P4360中第28个bit位（轴1使能标志位Physical Drive Enable State）        
            m_bIsEnableHR = channel.IsFlagSet(m_lAxis1Flags_P4361, 28); //读取P参数P4361中第28个bit位（轴2使能标志位Physical Drive Enable State）          
            m_bIsEnableKL = channel.IsFlagSet(m_lAxis2Flags_P4362, 28); //读取P参数P4362中第28个bit位（轴3使能标志位Physical Drive Enable State）            
            m_bIsEnableKR = channel.IsFlagSet(m_lAxis3Flags_P4363, 28); //读取P参数P4363中第28个bit位（轴3使能标志位Physical Drive Enable State）

            #region 伺服使能状态
            if ((m_bIsEnableHL == true) && (m_bIsEnableHR == true)
                && (m_bIsEnableKL == true) && (m_bIsEnableKR == true))
            {
                Controller_State.Controller_AllMotion_DriveOn = true;
            }
            else
            {
                Controller_State.Controller_AllMotion_DriveOn = false;
            }
            #endregion
        }

        internal void CheckLimitSwitch()
        {            
            Array GetPParms = channel.GetACRCustom("P4096");

            #region  限位开关
            m_iProgram1Flags_P4096 = Convert.ToInt32(GetPParms.GetValue(0));	//读取P4096的P参数 4096 Bit0-31 INP0-31
            m_bIsBit24 = channel.IsFlagSet(m_iProgram1Flags_P4096, 24);//读取P4096第24个bit参数位
            m_bIsBit25 = channel.IsFlagSet(m_iProgram1Flags_P4096, 25);//读取P4096第25个bit参数位
            m_bIsBit26 = channel.IsFlagSet(m_iProgram1Flags_P4096, 26);//读取P4096第26个bit参数位
            m_bIsBit27 = channel.IsFlagSet(m_iProgram1Flags_P4096, 27);//读取P4096第27个bit参数位
            m_bIsBit28 = channel.IsFlagSet(m_iProgram1Flags_P4096, 28);//读取P4096第28个bit参数位
            m_bIsBit29 = channel.IsFlagSet(m_iProgram1Flags_P4096, 29);//读取P4096第29个bit参数位
            m_bIsBit30 = channel.IsFlagSet(m_iProgram1Flags_P4096, 30);//读取P4096第30个bit参数位
            m_bIsBit31 = channel.IsFlagSet(m_iProgram1Flags_P4096, 31);//读取P4096第31个bit参数位
            #endregion

            #region 限位开关触发
            if (m_bIsBit24 || m_bIsBit25 || m_bIsBit26 || m_bIsBit27
                || m_bIsBit28 || m_bIsBit29 || m_bIsBit30 || m_bIsBit31)
            {
                Controller_State.Controller_LimitSwitch = true;
            }
            else
            {
                Controller_State.Controller_LimitSwitch = true;
            }
            #endregion
        }

        internal void AxisGroupStateRead()
        {
            Array GetPParms = channel.GetACRCustom("P4112");
            #region 轴组状态(Parker提供）
            m_iProgram1Flags_P4112 = Convert.ToInt32(GetPParms.GetValue(0));//读取P4112的P参数
            AxisGroup_State.Group_Acc = channel.IsFlagSet(m_iProgram1Flags_P4112, 0);
            AxisGroup_State.Group_Dec = channel.IsFlagSet(m_iProgram1Flags_P4112, 1);
            AxisGroup_State.Group_Stp = channel.IsFlagSet(m_iProgram1Flags_P4112, 2);
            AxisGroup_State.Group_Jek = channel.IsFlagSet(m_iProgram1Flags_P4112, 3);
            AxisGroup_State.Group_InMotion = channel.IsFlagSet(m_iProgram1Flags_P4112, 4);
            AxisGroup_State.Group_MVBF = channel.IsFlagSet(m_iProgram1Flags_P4112, 5);
            AxisGroup_State.Group_Feedholding = channel.IsFlagSet(m_iProgram1Flags_P4112, 6);
            AxisGroup_State.Group_InFeedhold = channel.IsFlagSet(m_iProgram1Flags_P4112, 7);
            #endregion
        }

        /* 检查驱动器错误（Drive fault input）*/
        internal void CheckDFI()
        {
            Array GetPParms = channel.GetACRCustom("P4098");

            #region 驱动器错误（Drive fault input）
            m_iProgram1Flags_P4098 = Convert.ToInt32(GetPParms.GetValue(0));
            m_bIsBit64 = channel.IsFlagSet(m_iProgram1Flags_P4098, 0);
            m_bIsBit65 = channel.IsFlagSet(m_iProgram1Flags_P4098, 1);
            m_bIsBit66 = channel.IsFlagSet(m_iProgram1Flags_P4098, 2);
            m_bIsBit67 = channel.IsFlagSet(m_iProgram1Flags_P4098, 3);
            #endregion

            #region 驱动器错误状态
            if (m_bIsBit64 || m_bIsBit65 || m_bIsBit66 || m_bIsBit67)
            {
                Controller_State.Controller_Drives_Fault = true;
            }
            else
            {
                Controller_State.Controller_Drives_Fault = false;
            }
            #endregion
        }

        internal void BitParameterRead()//限位开关的bit位参数读取
        {
            /*机器人P参数，获取Program2和IO口状态*/
            string m_strBitParameter = "P4130,P4103";
            Array BitParamrValue = channel.GetACRCustom(m_strBitParameter);

            #region Program2相关
            m_iProgram1Flags_P4130 = Convert.ToInt32(BitParamrValue.GetValue(0));	//读取P4130的P参数 
            m_bIsBit1088 = channel.IsFlagSet(m_iProgram1Flags_P4130, 0);//读取P4130第0个bit参数位Program2 Running判断程序是否在运行
            #endregion

            #region 自定义参数255
            m_iProgram1Flags_P4103 = Convert.ToInt32(BitParamrValue.GetValue(1));	//读取P4103的P参数
            m_bIsBit255 = channel.IsFlagSet(m_iProgram1Flags_P4103, 31);//读取P4103第31个bit参数位
            #endregion
        }

        #endregion
      
        internal void ElePutter_UP()//电动推杆向上运动
        {
            channel.SetFlag(32, true, true);//Bit32置位，33不置位
            channel.SetFlag(33, false, true);
        }

        internal void ElePutter_Down()//电动推杆向下运动
        {
            channel.SetFlag(33, true, true);//Bit33置位，32不置位
            channel.SetFlag(32, false, true);
        }

        internal void ElePutter_Stop()//电动推杆停止运动
        {
            channel.SetFlag(32, false, true);//Bit32置位，33不置位
            channel.SetFlag(33, false, true);
        }      

        internal void ParkerProgram2Start()//启动Program2
        {
            channel.SetFlag(255, true, true);//使用用户自定义Bit位
            channel.SetFlag(1096, true, true);//启动Program2 Bit位 
        }

        internal void ParkerProgram2Stop()//stop Program2
        {
            channel.SetFlag(255, false, true);//使用用户自定义Bit位
            channel.SetFlag(1096, false, true);//启动Program2 Bit位
            
        }
       
        #endregion

    }
}
